/*
 *  reader.c
 *  scheme2
 *
 *  Created by Leo Katzenstein on 5/25/07.
 *  Copyright 2007 __MyCompanyName__. All rights reserved.
 *
 */
# include "scheme.h"

/* enum Token1 { LEFT1, RIGHT1, tNUM, tSYM }; */
char buf[500];
Pair *atom;   /* when the token is an atom, this will be set */

/* nyi -- not yet implimented error message
          does not return
 */
void nyi( char *what )
{
	fprintf( stderr, "%s is not yet implemented.\nExiting.\n", what );
	exit( 3 );
}

void error( char *msg )
{
	fprintf( stderr, "Error: %s\n", msg );
	exit( 1 );
}

int is_white( int ch )
{
	if ( ch == ' ' || ch == '\n' || ch == '\t' )
		return TRUE;
	else
		return FALSE;
}

int is_break( int ch )
{
	if ( ch == EOF ||
	     ch == '(' ||
		 ch == ')' ||
		 is_white( ch ) )
		return TRUE;
	else
		return FALSE;
}


int gettok()
{
	/* int ch; */
	int n;
	int isnum;
	int token;
			
	n = 0;
	isnum = TRUE;
	
	token = yylex();

	return token;
#ifdef NOTDEF	
	/* skip white space */
	while ( is_white( ch = getc(f) ))
		;
	
	/* we're looking at a nonwhite char */
	if ( ch == EOF )
		return EOF;
	if ( ch == '(' )
		return LEFT;
	if ( ch == ')' )
		return RIGHT;
	
	do {
		buf[ n++ ] = ch;
		if ( !isdigit( ch ) )
			isnum = FALSE;
	} while ( ! is_break( ch = getc( f ) ) );
	buf[n] = '\0';	/* terminate the string */
	ungetc( ch, f );
	if ( isnum )
	{
		atom = new( Pair );
		atom->car = (Pair *) NUMBER;
		atom->cdr = (Pair *) atoi( buf );
		return tNUM;
	}
	else
	{
		atom = make_sym( strdup( buf ) );
		return tSYM;
	}
#endif
}

/* read an expression */
Pair *readexp()
{
	enum Token t;
	char str[80];
	
	switch ( (t = gettok()) )
	{
		case 0:
			return (Pair *) EOF;

		case LEFT:
			return readlist();

		case RIGHT:
			/* nyi( "RIGHT" );   <= this is the key !! */
			return (Pair *) RIGHT;
		
		case tSYM:
			return make_sym(yytext);

		case tFIXNUM:
			return make_num(atol(yytext));

		case tFLOAT:
			return make_double(atof(yytext));

		case tQUOTE:	        
			return cons(quote, cons(readexp(), NULL));

		default:
			sprintf( str, "unrecognized token type %d", t );
			error( str );
	}
	error( "internal error - should never get here" );
	return NULL;
}

/* readlist - read a list
 * This has been called after the opening left paren has been seen
 */
Pair *readlist()
{
	Pair list_head;
	Pair *tail;
	Pair *e;
	
	list_head.cdr = (unsigned long) NULL;
	tail = &list_head;
	for (;;)
	{ 
		e = readexp();
		if ( e == (Pair *) EOF )
			error( "unexpected EOF in readlist" );
		else if (e == (Pair *) RIGHT )
			return list_head.cdr;
		else {
			/* some sort of sexp, either an atom or a list */
			tail->cdr = cons( e, NULL );
			tail = tail->cdr;
		}
	}
}
